﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RW.Data.Graph;
using RW.Data.Objects;

namespace RW.Data
{
    public class Query2
    {
        public List<string> Program { get; set; }
        public Dictionary<string, bool> Conditions { get; set; }
        public Dictionary<string, bool> Target { get; set; }

        private MultiGraph graph;

        public Query2(MultiGraph multiGraph)
        {
            Program = new List<string>();
            Conditions = new Dictionary<string, bool>();
            Target = new Dictionary<string, bool>();
            graph = multiGraph;
        }

        public string Compute(bool isAlways)
        {
            try
            {
                List<State> startingVertices;
                if (Conditions.Count == 0) //jesli user nie okresli w inpucie to brane są tylko initial states (zgodnie z opisem w dokumentacji)
                    startingVertices = graph.Vertices.Where(v => v.IsInitial == true).ToList();
                else
                    startingVertices = graph.Vertices.Where(v => v.SatisfiesConditions(Conditions)).ToList();
                int counter = 0;
                foreach (var vertex in startingVertices)
                {
                    bool currentResult = GoingDeep(vertex, counter, isAlways);
                    if (isAlways)
                    {
                        if (!currentResult)
                            return "false";
                    }
                    else
                    {
                        if (currentResult)
                            return "true";
                    }
                }
                return isAlways.ToString();
            }
            catch (Exception e)
            {
                if (e.GetType() == typeof(BrokenPathException))
                    return "false";
                return "error";
            }
        }

        public bool GoingDeep(State vertex, int counter, bool isAlways)
        {
            if (counter == Program.Count())
                return vertex.Equals(Target);
            var edges = graph.OutEdges(vertex).Where(e => e.ActionName.Equals(Program[counter]));
            if (edges.Count() == 0 && isAlways)
                throw new BrokenPathException("Ścieżka przerwana co w przypadku Q1-always jest niedopuszczalne");
            foreach (var edge in edges)
            {
                bool currentResult = GoingDeep(edge.Target, counter + 1, isAlways);
                if (isAlways)
                {
                    if (!currentResult)
                        return false;
                }
                else
                {
                    if (currentResult)
                        return true;
                }
            }
            return isAlways;
        }
    }
}
